package threading;

// 线程池的模拟实现
// 【阻塞队列】：这是线程安全的，不用额外加锁！！

// Thread跑起来之后是不会被销毁的，这和普通对象是不一样的
// Thread在执行过程中是不会提前销毁的；但是Thread中的run执行完了就会销毁Thread了。

// 这是一个固定线程数目的线程池

// 如果想要线程池数目动态，则需要在发现这个任务没有线程去执行时添加新线程

// 不用结束，因为无法判定啥时候会有新的线程过来，
// 如果非要结束，那就单独写一个shutdown方法强制所有interrupt所有的工作线程

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

// 模拟实现 【线程池】
class MyThreadPool {
    // 阻塞队列
    private BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>();

    // submit方法
    public void submit(Runnable runnable) throws InterruptedException {
        // 提交任务，存入阻塞队列中
        queue.put(runnable);
    }

    // 构造方法
    public MyThreadPool(int m) {
        // m个线程处理完成工作
        // 一个线程完成一个工作其实就是：从队列中取出一个任务并执行该任务
        // 执行完该任务之后其实该任务也就出队列了
        for (int i = 0; i < m; i++) {
            // 创建线程完成工作
            Thread t = new Thread(() -> {
                // 出队列:拿到一个任务并执行
                // 直接这样等的话，一个线程只会对应执行一个任务，最后执行任务数量就等于线程数
                // 不是预期结果，预期是一个线程可以处理多个任务

                // 而使用while循环的效果其实是：
                // 取出的任务去持续扫描所有线程，那个空闲就使用哪个线程！！
                while (true) {
                    try {
                        Runnable runnable = queue.take();
                        runnable.run();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

            });
            t.start();
        }
    }
}

public class Demo6 {
    public static void main(String[] args) throws InterruptedException {
        // 创建10个线程
        MyThreadPool pool = new MyThreadPool(10);
        // 给任务
        for (int i = 0; i < 1000; i++) {
            int taskId = i;
            // 任务提交到队列中
            pool.submit(new Runnable() {
                @Override
                public void run() {
                    System.out.println("执行当前任务"+ taskId + " 当前线程-"+Thread.currentThread().getId());
                }
            });
        }
    }
}
